﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Legend.Object;
using Legend.Component.Ground;
using Legend.Component.Interface;
using Legend.Component.Hero;
using Legend.Component.Common;

using Legend.Mesh;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Audio;

namespace LegendMain.TestBed
{
    class TestMesh : ITestBed
    {
        private float fov = 35.0f;
        enum GameState
        {
            InsertCoin,
            StartReady,
            Starting,
            Started,
            
        }
        
        GameObject camera;
        GameObject hero;
        GameObject ground;
        ContentManager currentContentManager;
        SpriteFont font;
        SpriteBatch spriteBatch;
        GameState state = GameState.InsertCoin;
        Texture2D insertCoinTexture;
        Texture2D startingTexture;
        SoundEffect startingSound;
        SoundEffect mainTheme;
        int startingTime;

        public TestMesh()
        {
        }

        public bool LoadContent(GraphicsDevice device, ContentManager contentManager)
        {
            GameObjectManager.Contents = contentManager;
            GameObjectManager.SetBoardValue("Life", 3);
            GameObjectManager.SetBoardValue("Score", 0);
            GameObjectManager.SetBoardValue("Combo", 0);

            startingSound = contentManager.Load<SoundEffect>("titleSound");
            mainTheme = contentManager.Load<SoundEffect>("maintheme");
            insertCoinTexture = Texture2D.FromFile(device, "Content/insertcoin.png");
            startingTexture = Texture2D.FromFile(device, "Content/starting.png");

            currentContentManager = contentManager;

            ground = new GameObject();
            hero = new GameObject();
            camera = new GameObject();

            {
                GroundRenderable groundRender = ground.CreateComponent<GroundRenderable>();
                LinearMovement movement = ground.CreateComponent<LinearMovement>();
                movement.Velocity = new Vector3(0, -100, 0);
                groundRender.LoadResource(contentManager);
            }

            {
                FixedMovement movement = camera.CreateComponent<FixedMovement>();
                movement.Position = new Vector3(0, -900f, 900f);
                movement.Direction = new Vector3(0, 900f, -800f);
            }

            {
                KeyboardProcessor processor = hero.CreateComponent<KeyboardProcessor>();
                processor.MaxSpeed = 300f;
                processor.Acceleration = 0;// 1000f;
                //processor.MovingBoundary = new BoundingBox(new Vector3(-350f, -400f, -100f), new Vector3(350, 600, 100));

                FixedMovement movement = hero.CreateComponent<FixedMovement>();
                movement.Position = new Vector3(0, -100, 5);
                movement.Rotate(Vector3.Backward, (float)Math.PI);

                SimpleRenderable renderable = hero.CreateComponent<SimpleRenderable>();
                renderable.LoadModel(contentManager, "hero");

                FirstWeapon weapon = hero.CreateComponent<FirstWeapon>();
                weapon.FireSpeed = 0.3f;

                Collision collision = hero.CreateComponent<Collision>();
                collision.LocalBoundingBox = Legend.Helper.Mesh.GetModelBoundingBox(renderable.Model);

                HeroDamaging damaging = hero.CreateComponent<HeroDamaging>();
                damaging.Damage = 10;

                StateManager statemg = hero.CreateComponent<StateManager>();
            }

            font = contentManager.Load<SpriteFont>("Forte");
            spriteBatch = new SpriteBatch(device);

            return true;
        }

        public void Update(GameTime gameTime)
        {
            switch (state)
            {
                case GameState.InsertCoin:
                    if (Keyboard.GetState().IsKeyDown(Keys.Space))
                    {
                        startingSound.Play(1, 0, 0.2f, false);
                        state = GameState.StartReady;
                        startingTime = gameTime.TotalGameTime.Seconds;
                    }
                    break;

                case GameState.StartReady:
                    if ((gameTime.TotalGameTime.Seconds - startingTime) > 7)
                    {
                        state = GameState.Starting;
                    }
                    break;

                case GameState.Starting:
                    GameObjectManager.RegistGameObject(ground);
                    GameObjectManager.RegistGameObject(camera);
                    GameObjectManager.RegistGameObject(hero);

                    MonsterGenerator.Initialize(currentContentManager);
                    PropGenerator.Initialize(currentContentManager);

                    mainTheme.Play(1, 0, 0, true);
                    state = GameState.Started;

                    break;

                case GameState.Started:
                    PropGenerator.Update(gameTime);
                    MonsterGenerator.Update(gameTime);

                    GameObjectManager.Update(gameTime, currentContentManager);
                    break;
            }

        }

        public void Draw(GraphicsDevice graphicsDevice, GameTime gameTime)
        {
            switch (state)
            {
                case GameState.InsertCoin:
                    spriteBatch.Begin();
                    spriteBatch.Draw(insertCoinTexture, new Rectangle(0, 0, graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height), Color.White);
                    spriteBatch.End();
                    break;

                case GameState.StartReady:
                    spriteBatch.Begin();
                    spriteBatch.Draw(startingTexture, new Rectangle(0, 0, graphicsDevice.Viewport.Width, graphicsDevice.Viewport.Height), Color.White);
                    spriteBatch.End();
                    break;

                case GameState.Starting:
                    break;

                case GameState.Started:
                    IMovement orientation = camera.FindComponent<IMovement>();
                    Matrix view = Matrix.CreateLookAt(orientation.Position, orientation.Position + orientation.Direction, Vector3.Up);
                    Matrix projection = Matrix.CreatePerspectiveFieldOfView(MathHelper.ToRadians(fov), 1.0f, 1.0f, 10000.0f);

                    GameObjectManager.Render(graphicsDevice, view, projection);

                    spriteBatch.Begin();
                    int yOffset = 10;
                    foreach (KeyValuePair<string, int> pair in GameObjectManager.Board)
                    {
                        string output = pair.Key + " : " + pair.Value.ToString();
                        spriteBatch.DrawString(font, output, new Vector2(10, yOffset), Color.White);
                        yOffset += 20;
                    }
                    spriteBatch.End();
                    break;
            }

        }
    }
}
